package net.pingfang.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class DateUtil {
    public static final String TYPE_ONE = "yyyyMMddHHmmss";

    public static final String TYPE_TWO = "yy-MMM-dd HHmm";
    public static final String TYPE_SEVEN = "yyyy-MM-dd";
    public static final String TYPE_EIGHT = "yyyyMMdd";
    public static final String TYPE_TEN = "MM-dd";
    public static final String TYPE_ELEVEN = "yyyy/MM/dd HH:mm:ss";
    public static final String TYPE_NINTH = "yyyy-MM-ddHH:mm";

    public static final String TYPE_THREE = "yyyy-MM-dd HH:mm:ss";

    public static final String TYPE_FOUR = "yyyy-MM-dd'T'HH:mm:ss";

    public static final String TYPE_FIVE = "yyyyMMddHHmmssSSS";

    public static final String TYPE_SIX = "yyyy-MM-dd HH:mm:ss.SSS";


    /**
     * 获取当前系统时间并按指定的日期类型格式化
     *
     * @param dateType 设置日期格式
     * @return
     */
    public static String getDate(String dateType) {
        SimpleDateFormat df = new SimpleDateFormat(dateType);//设置日期格式
        return df.format(new Date());
    }

    /**
     * 获取当前系统时间并按指定的日期类型格式化
     *
     * @param dateType 设置日期格式
     * @return
     */
    public static String getDate(String dateType, Date date) {
        SimpleDateFormat df = new SimpleDateFormat(dateType);//设置日期格式
        return df.format(date);
    }

    /**
     * 获取时间的平均差值
     *
     * @param timeList 时间集合
     * @return
     */
    public static String getAvgDiff(List<String> timeList) {
        if (timeList == null || timeList.size() == 0){
            return null;
        }
        SimpleDateFormat df = new SimpleDateFormat(TYPE_THREE);//设置日期格式
        long firstTime = 0L;
        long totalDiffTime = 0L;
        for (String time : timeList) {
            try {
                Date date = df.parse(time);
                if (firstTime==0L){
                    firstTime = date.getTime();
                    continue;
                }
                totalDiffTime += date.getTime() - firstTime;
                firstTime = date.getTime();
            } catch (ParseException e) {
                return null;
            }
        }

        return getTime(totalDiffTime/timeList.size()-1);
    }

    public static String getTime(Long time) {
        String timeStr="";
        if (time==null){
            return null;
        }
        //时
        Long hour = time / 60 / 60;
        //分
        Long minutes = time / 60 % 60;
        //秒
        Long remainingSeconds = time % 60;
        //判断时分秒是否小于10……
        if (hour < 10){
            timeStr =  minutes + "分" + remainingSeconds+"秒";
        }else if (minutes < 10){
            timeStr =  minutes + "分" + remainingSeconds+"秒";
        }else if (remainingSeconds < 10){
            timeStr =  minutes + "分" + "0" + remainingSeconds+"秒";
        }else {
            timeStr =  minutes + "分" + remainingSeconds+"秒";
        }
        return timeStr;
    }

    public static List<String> getBeforeHour(int hour){
        List<String> result = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
        for (int index = 0; index < hour; index++) {
            if (currentHour < 0){
                currentHour = 23;
            }
            result.add(String.valueOf(currentHour));
            currentHour--;
        }
        Collections.reverse(result);
        return result;
    }

    /**
     * 日期格式转换
     *
     * @param originType 原始类型
     * @param dateStr    日期字符串
     * @param newType    目标类型
     */
    public static String parseDate(String originType, String newType, String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        try {
            SimpleDateFormat originalDf = new SimpleDateFormat(originType, Locale.ENGLISH);
            SimpleDateFormat df = new SimpleDateFormat(newType, Locale.ENGLISH);
            return df.format(originalDf.parse(dateStr));
        } catch (ParseException e) {
            return dateStr;
        }
    }

    /**
     * 日期格式转换
     */
    public static Long parseDate(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            SimpleDateFormat originalDf = new SimpleDateFormat(TYPE_NINTH, Locale.ENGLISH);
            return originalDf.parse(date).getTime();
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 日期格式转换
     */
    public static Long parseTime(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            SimpleDateFormat originalDf = new SimpleDateFormat(TYPE_THREE, Locale.ENGLISH);
            return originalDf.parse(date).getTime();
        } catch (ParseException e) {
            return null;
        }
    }

    public static Long calculateDataDifference(String endTime, String startTime) {
        if (StringUtils.isEmpty(endTime) || StringUtils.isEmpty(startTime)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(TYPE_THREE, Locale.ENGLISH);
        try {
            return (sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime()) / 1000;
        } catch (ParseException e) {
            return null;
        }
    }

    public static long calculateDayDifference(String endTime, String startTime) {
        if (StringUtils.isEmpty(endTime) || StringUtils.isEmpty(startTime)) {
            return 0;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(TYPE_SEVEN, Locale.ENGLISH);
        try {
            return (sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime()) / 1000/ 60/60/24;
        } catch (ParseException e) {
            return 0;
        }
    }

    public static boolean checkIsInTimes(String startTime, String endTime, String time) {
        if (StringUtils.isEmpty(endTime) || StringUtils.isEmpty(startTime)) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(TYPE_SEVEN, Locale.ENGLISH);
        try {
            long start = sdf.parse(startTime).getTime();
            Date parse = sdf.parse(endTime);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(parse);
            calendar.add(Calendar.DATE, 1);
            long end = calendar.getTime().getTime();
            long now;
            if (!StringUtils.isEmpty(time)){
                now = sdf.parse(time).getTime();
            }else {
                now = new Date().getTime();
            }
            return now >= start && now < end;
        } catch (ParseException e) {
            return false;
        }
    }

    public static Long calculateHourDifference(String endTime, String startTime) {
        if (StringUtils.isEmpty(endTime) || StringUtils.isEmpty(startTime)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(TYPE_THREE, Locale.ENGLISH);
        try {
            return (sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime()) / (1000 * 60 * 60);
        } catch (ParseException e) {
            return null;
        }
    }

    public static Double calculateHourDifference(String endTime, String startTime, int length,
                                                 RoundingMode roundingMode) {
        if (StringUtils.isEmpty(endTime) || StringUtils.isEmpty(startTime)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(TYPE_THREE, Locale.ENGLISH);
        try {
            return BigDecimal.valueOf((float) (sdf.parse(endTime).getTime() - sdf.parse(startTime).getTime()) / (1000 * 60 * 60)).setScale(length, roundingMode).doubleValue();
        } catch (ParseException e) {
            return null;
        }
    }

    public static Long getCurrentTime() {
        return new Date().getTime();
    }

    public static LocalDateTime getLocalDateTime(){
        return LocalDateTime.now();

    }

    public static LocalDateTime getLocalDateTime(String type){
        String format = LocalDateTime.now().format(DateTimeFormatter.ofPattern(type));
        return LocalDateTime.parse(format, DateTimeFormatter.ofPattern(type));
    }

    public static LocalDateTime parseLocalDateTime(String date, String type){
        if (StringUtils.isEmpty(date)){
            return null;
        }
        try{
            return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(type));
        }catch (Exception exception){
            return getLocalDateTime();
        }
    }

    public static String getWeek(){

        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0){
            w = 0;
        }
        return weekDays[w];

    }

    public static Long getDayTime(Integer checkHour) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.set(Calendar.HOUR_OF_DAY, checkHour);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND,0);
        System.out.println(cal.getTime());
        return cal.getTime().getTime();
    }

    /**
     * 增加天数
     *
     * @return
     */
    public static String addDay(String currentDay, long num) {
        SimpleDateFormat originalDf = new SimpleDateFormat(TYPE_SEVEN, Locale.ENGLISH);
        try {
            long newTime = originalDf.parse(currentDay).getTime() + num*1000 * 60 * 60 * 24;
            return originalDf.format(new Date(newTime));
        } catch (ParseException e) {
            return null;
        }
    }

    private static List<String> getNearWeek(LocalDate currentDate) {
        currentDate = currentDate == null ? LocalDate.now() : currentDate;
        List<String> nearWeekList = new ArrayList<>();
        String day = null;
        for (int i = 6; i > 0; i--) {
            day = currentDate.minusDays(i).toString();
            nearWeekList.add(day);
        }
        nearWeekList.add(currentDate.toString());
        return nearWeekList;
    }

    public static void main(String[] args) {
        System.out.println(getNearWeek(LocalDate.now()));
    }

    /**
     * 根据基准日期计算具体日期是第几周
     * @param currentDate
     * @param waitCalculateDay
     * @return
     */
    public static String getWeekOfMonth(LocalDate currentDate, LocalDate waitCalculateDay) {
        Long cha = currentDate.toEpochDay() - waitCalculateDay.toEpochDay();
        //7天为一周
        //倍数
        long multiple = cha / 7;
        //余数
        long remainder = cha % 7;
        return "第" + (4 - multiple) + "周";
    }

    /**
     * 根据基准日期计算具体日期是第几月
     * @param currentDate
     * @param waitCalculateDay
     * @return
     */
    public static String getMonthOfQuarter(LocalDate currentDate, LocalDate waitCalculateDay) {
        Long cha = currentDate.toEpochDay() - waitCalculateDay.toEpochDay();
        //30天为一月
        //倍数
        long multiple = cha / 30;
        //余数
        long remainder = cha % 30;
        return "第" + (4 - multiple) + "月";
    }
}
